/**
 * 判断文件夹是否存在
 * @param path
 * @param mkdir
 * @returns {boolean}
 */

const { ncepPath } = require("./config/config");
const { url } = require("./config/ncep.config");
const { Grib2ToJson } = require("./plugin");
const moment = require("moment");
const path = require("path");
const { isArray } = require("./is");

const fs = require("fs");

const axios = require("axios");
const SliceServer = require("./sliceServer");

const checkFolderExist = (path, mkdir) => {
  if (!fs.existsSync(path)) {
    if (mkdir) {
      fs.mkdirSync(path, { recursive: true });
    }
    return false;
  } else {
    return true;
  }
};

const parserInvoker = {
  levelInvoker: (levelKey) => {
    if (levelKey === "all") {
      return "all_lev";
    } else {
      const _s = levelKey.split(" ");

      return `lev_${_s.join("_")}`;
    }
  },
  extentInvoker: (extent) => {
    if (isArray(extent) && Array.length === 4) {
      return {
        leftlon: extent[0],
        rightlon: extent[2],
        toplat: extent[3],
        bottomlat: extent[1],
      };
    } else {
      return {
        leftlon: -180,
        rightlon: 180,
        toplat: 85,
        bottomlat: -85,
      };
    }
  },
};

const zeroize = function (val, filLength = 3) {
  return Number(val).toFixed().padStart(filLength, "0");
};

/**
 *
 * @param {*} target
 * @param {Array} ExtraParams
 * @returns
 */
const rejectExtraParams = function (target, ExtraParams) {
  return Object.fromEntries(
    Object.entries(target).filter(([key]) => !ExtraParams.includes(key))
  );
};

const CreatePath = (modelName, currentTime, levels, times) => {
  const _path = ncepPath.path;
  for (const level of levels) {
    const source_path = path.join(
      ...[_path, currentTime, times, modelName, level.key, ncepPath.sourceName]
    );

    const parser_path = path.join(
      ...[_path, currentTime, times, modelName, level.key, ncepPath.parseName]
    );

    const grayscale_path = path.join(
      ...[
        _path,
        currentTime,
        times,
        modelName,
        level.key,
        ncepPath.grayscaleName,
      ]
    );
    //创建源文件路劲
    checkFolderExist(source_path, true);
    checkFolderExist(parser_path, true);
    checkFolderExist(grayscale_path, true);
  }

  return path.join(...[ncepPath.path, currentTime, times, modelName]);
};

const MergeUrl = (
  eleKey,
  levels,
  times,
  interval,
  startTime,
  startAging,
  endAging
) => {
  let urlParams = [];

  for (
    let i = Number(startAging);
    i < Number(endAging);
    i += Number(interval)
  ) {
    for (const level of levels) {
      const urlParam = {};
      const name = moment(startTime).format("YYYYMMDDHH");
      const dir = moment(startTime).hours(Number(times)).format("YYYYMMDD_HH");
      urlParam["file"] = `gfs.t${times}z.pgrb2.${url.file_type}.f${zeroize(i)}`;
      urlParam[`${parserInvoker.levelInvoker(level.key)}`] = "on";
      urlParam[`var_${eleKey}`] = "on";
      urlParam["dir"] = `/gfs.${moment(startTime)
        .hours(Number(times))
        .format("YYYYMMDD/HH")}/atmos`;
      urlParam["subregion"] = "on";

      Object.assign(urlParam, parserInvoker.extentInvoker(url.extent));

      urlParam["params"] = {
        fileName: name + `.${zeroize(i)}`,
        levelPath: level.key,
      };
      urlParams.push(urlParam);
    }
  }
  return urlParams;
};

const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));

const ParserUrl = ({ baseUrl, baseDir, file_suffix }) => {
  const _baseUrl = baseUrl,
    _file_suffix = file_suffix,
    _baseDir = baseDir;

  return async function (params) {
    try {
      for (let i = 0; i < params.length; i++) {
        const _params = params[i].params;
        const res = await axios({
          method: "GET",
          url: _baseUrl,
          responseType: "stream",
          params: rejectExtraParams(params[i], ["params"]),
        });

        if (res.status !== 200) {
          console.log(`文件${_params.fileName} 不存在`);
        } else {
          const filePath = path.join(
            ...[
              _baseDir,
              _params.levelPath,
              ncepPath.sourceName,
              _params.fileName + _file_suffix,
            ]
          );

          const stream = fs.createWriteStream(filePath);
          res.data.pipe(stream);

          stream.on("finish", () => {
            stream.close();
            console.log(`保存文件${_params.fileName}成功`);

            const output_path = path.join(
              ...[
                _baseDir,
                _params.levelPath,
                ncepPath.parseName,
                _params.fileName + ".json",
              ]
            );

            Grib2ToJson(filePath, {
              output: output_path,
              data: true,
            }).then((json) => {
              const grayscale_base_path = path.join(
                ...[
                  _baseDir,
                  _params.levelPath,
                  ncepPath.grayscaleName,
                  _params.fileName,
                ]
              );

              SliceServer({
                startLevel,
                endLevel,
                filePath: output_path,
                outputPath: grayscale_base_path,
              });
            });
          });

          stream.on("error", function (e) {
            console.log(`保存文件${_params.fileName}失败:${e}`);
          });
        }

        //防止请求平凡导致美国气象中心封IP 休眠三秒钟
        await sleep(3000);
      }
    } catch (error) {
      console.error(`系统出现错误:错误内容——> ${error.message}`);
    }
  };
};

const resolves = (_path) => path.resolve(__dirname, "..", _path);

module.exports = {
  CreatePath,
  MergeUrl,
  ParserUrl,
  checkFolderExist,
  resolves
};
